import { SubjectComponent } from "../../../../core/subject";

const { ccclass, property } = cc._decorator;


@ccclass
export default class BoxImageView extends SubjectComponent {
    _blocked = false;


    @property(cc.Sprite)
    face: cc.Sprite = null;

    originWp = cc.v2();
    originScale = 1;

    touches: TouchHandle[] = [];
    touchDis = 0;
    touchDisDelta = 0;
    touchRad = 0;
    touchRadDelta = 0;
    movePt = cc.v2();

    init(frame: cc.SpriteFrame, wp = cc.v2(), scale = 1, wrap = true) {
        this.originWp = wp;
        this.originScale = scale;
        this.face.spriteFrame = frame;

        cc.director.once(cc.Director.EVENT_AFTER_UPDATE, () => {
            this.reset(wrap);
        }, this);
    }
    reset(wrap = true) {
        let np = this.node.convertToNodeSpaceAR(this.originWp);
        this.face.node.setPosition(np);
        this.face.node.scale = this.originScale;

        if (wrap) {
            let w = Math.min(this.node.width, this.face.node.width);
            let h = Math.min(this.node.height, this.face.node.height);
            let ph = Math.max(w / this.face.node.width, h / this.face.node.height);
            cc.Tween.stopAllByTarget(this.face.node);
            cc.tween(this.face.node).to(0.25, { x: 0, y: 0, scale: ph, angle: 0 }, { easing: "sineInOut" }).start();
        }
    }

    protected onLoad(): void {
        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
        this.node.on(cc.Node.EventType.MOUSE_WHEEL, this.onMouseWheel, this);
    }
    protected onDestroy(): void {
        this.emit("destroy");
    }
    onMouseWheel(evt: cc.Event.EventMouse) {
        let ts = this.face.node.scale;
        if (evt.getScrollY() > 0) {
            ts += 0.1;
        }
        else {
            ts -= 0.1;
        }

        if (ts < 0.1) {
            ts = 0.1;
        }
        else if (ts > 2) {
            ts = 2;
        }

        this.face.node.scale = ts;
    }
    onTouchStart(evt: cc.Event.EventTouch) {
        if (this._blocked) {
            return;
        }

        let loc = evt.getLocation();
        let id = evt.getID();

        let touch = this.touches.find(ele => ele.id == evt.getID());
        if (!touch) {
            touch = new TouchHandle(id);
            touch.dis = 0;
            this.touches.push(touch);
        }
        touch.loc = loc.clone();
        touch.delta = cc.v2();
        if (this.touches.length > 1) {
            let t1 = this.touches[0];
            let t2 = this.touches[1];
            this.touchDis = t1.loc.sub(t2.loc).mag();
            this.touchRad = t1.loc.sub(t2.loc).signAngle(cc.Vec2.RIGHT);
            this.movePt = t1.loc.lerp(t2.loc, 0.5);
        }

    }
    onTouchMove(evt: cc.Event.EventTouch) {
        if (this._blocked) {
            return;
        }
        let loc = evt.getLocation();
        let delta = evt.getDelta();
        let id = evt.getID();
        let touch = this.touches.find(ele => ele.id == evt.getID());
        if (!touch) {
            touch = new TouchHandle(id);
            this.touches.push(touch);
        }
        touch.loc = loc.clone();
        touch.delta = delta;
        touch.dis += delta.mag();
        let moveDv = cc.v2();

        if (this.touches.length > 1) {
            let t1 = this.touches[0];
            let t2 = this.touches[1];
            let dis = t1.loc.sub(t2.loc).mag();
            let rad = t1.loc.sub(t2.loc).signAngle(cc.Vec2.RIGHT);
            let movePt = t1.loc.lerp(t2.loc, 0.5);

            moveDv = this.movePt.sub(movePt).neg();
            this.movePt = movePt;
            this.touchRadDelta = rad - this.touchRad;
            this.touchDisDelta = (dis - this.touchDis);
            let ts = this.face.node.scale + this.touchDisDelta / this.touchDis;
            if (ts < 0.1) {
                ts = 0.1;
            }
            else if (ts > 2) {
                ts = 2;
            }

            this.touchRad = rad;
            if (ts > 1.0) {
                this.touchDis = t1.loc.sub(t2.loc).mag();
            }
            else {
                this.touchDis = dis;
            }

            this.face.node.angle -= cc.misc.radiansToDegrees(this.touchRadDelta);
            this.face.node.scale = ts;
        }
        else {
            if (touch.dis >= 5) {
                moveDv = delta;
            }
        }

        if (!moveDv.equals(cc.Vec2.ZERO)) {
            this.face.node.x += moveDv.x;
            this.face.node.y += moveDv.y;
        }
    }
    onTouchEnd(evt: cc.Event.EventTouch) {
        if (this._blocked) {
            return;
        }

        let id = evt.getID();
        let foundInd = this.touches.findIndex(ele => ele.id == id);
        let touch = null;
        if (foundInd !== -1) {
            touch = this.touches.splice(foundInd, 1)[0];
        }

        if (this.touches.length === 0) {
            if (touch?.dis < 5) {
                this.close();
            }
        }
    }
    async close() {
        if (this._blocked) {
            return;
        }
        this._blocked = true;
        let np = this.node.convertToNodeSpaceAR(this.originWp);
        //回到pos

        this.face.node.angle %= 360;
        await new Promise<void>(ok => {
            cc.tween(this.face.node)
                .to(0.25, { x: np.x, y: np.y, scale: this.originScale, angle: 0 }, { easing: "sineInOut" })
                .call(ok)
                .start();
        });
        this.node.destroy();
    }
};